package com.gopay.bis.service.bank.impl;

import java.util.List;

import javax.annotation.Resource;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.gopay.bis.common.util.BisPayCheckUtils;
import com.gopay.bis.manager.bank.BankOrderManager;
import com.gopay.bis.manager.bank.external.BisPayMessageManager;
import com.gopay.bis.manager.bank.payconfig.BisBankExtConfigManager;
import com.gopay.bis.service.bank.BankOrderService;
import com.gopay.bis.service.bank.external.BisExternalPlatformService;
import com.gopay.common.Result;
import com.gopay.common.constants.bank.BankConstants;
import com.gopay.common.constants.bank.BankOrderStatus;
import com.gopay.common.constants.bank.BankOrderType;
import com.gopay.common.constants.bank.BisBankBusinessProd;
import com.gopay.common.constants.bank.BisBankInterfaceChannel;
import com.gopay.common.constants.proccode.ProcCodeConstants;
import com.gopay.common.cps.manager.order.CpsGeneralMainOrderQueryManager;
import com.gopay.common.domain.bank.BankOrder;
import com.gopay.common.domain.bank.BaseMessage;
import com.gopay.common.domain.bank.external.BisBankMerchant;
import com.gopay.common.domain.bank.external.BisPayMessage;
import com.gopay.common.domain.bank.umpay.ebank.UmPayMessage;
import com.gopay.common.domain.bis.BaseBisBankExtConfig;
import com.gopay.common.domain.cps.CpsGenMainOrder;
import com.gopay.common.exception.GopayException;
import com.gopay.common.order.bankorder.trade.InitialSpringBeanName;
import com.gopay.common.order.bankorder.trade.TradeType;
import com.gopay.common.util.spring.SpringContextUtil;
import com.gopay.remote.bank.BankInteractRemoteService;
import com.gopay.remote.bank.MtPayInteractRemoteService;

/**
 * 银行操作Service实现
 * 
 * @BankInteractServiceImpl.java
 * @author yaobo
 */
@Service("mtPaybankInteractService")
public class BankMtPayInteractServiceImpl implements MtPayInteractRemoteService {

	private static Logger logger = LoggerFactory.getLogger(BankMtPayInteractServiceImpl.class);

	@Resource(name = "bankOrderService")
	private BankOrderService bankOrderService;

    @Resource(name = "bisExternalPlatformService")
    private BisExternalPlatformService bisExternalPlatformService;
	
	@Resource(name = "cpsGeneralMainOrderQueryManager")
	private CpsGeneralMainOrderQueryManager mainOrderQuery;

	@Resource(name = "bankOrderManager")
	private BankOrderManager bankOrderManager;

	@Resource(name = "bisBankExtConfigManager")
	BisBankExtConfigManager bisBankExtConfigManager;
	
	@Resource(name = "bisPayMessageManager")
	BisPayMessageManager bisPayMessageManager;
	
	@Override
	public Result pay(BaseMessage base) {
		logger.error("BankInteractServiceImpl银行支付处理base对象："+ToStringBuilder.reflectionToString(base));
		Result result = new Result();
		try {
			// 获取订单信息与银行信息
			CpsGenMainOrder mainOrder = getMainOrder(base.getOrderId());
			// 获取SPRING加载的BeanName
			String beanName = getBeanName(mainOrder, base.getBankIntrChann(),base.getBankBusProd());
			base.setBankOrderId(base.getOrderId());
			MtPayInteractRemoteService bankService = (MtPayInteractRemoteService) SpringContextUtil.getBean(beanName);
			if(!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())){
				BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), base.getBank());
				//设置一级私钥路径
				base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
				//设置一级私钥密码
				base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
				//设置二级私钥路径
				base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
				//设置二级私钥密码
				base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
				//设置公钥路径
				base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
				//设置商户号
				base.setMerID(bankConfig.getIntrMernum1());
				//设置二级商户号
				base.setMerID2nd(bankConfig.getIntrMernum2());			
				//设置结算账户网点联行号
				base.setBranchCode(bankConfig.getBranchCode());
				//设置银行支付地址
				base.setPayUrl(bankConfig.getPayUrl());			
				//设置支付后台通知地址
				base.setPayRuturnUrl(bankConfig.getPayRuturnUrl());
				//设置支付后前通知地址
				base.setPayNotifyUrl(bankConfig.getPayNotifyUrl());	
			}
			// 校验银行订单不能为多条,此处以后修改
            List<BankOrder> bankOrders =  bankOrderService.getBankOrdersByGopayOrderId(base.getOrderId());
            if(bankOrders!=null && bankOrders.size()>0){
                result.setResultCode(ProcCodeConstants.PROC_CODE_100E5015);// 已存在相同的订单
                result.setSuccess(false);
                return result;
            }
			// 新增bankOrder info
            base.setBankOrderType(BankOrderType.GOPAY_BIS_ORDER);//订单类型：新平台订单
			bankOrderService.addBankOrder(base);
			//签名
			result = bankService.pay(base);
			base = (BaseMessage)result.getDefaultModel();
			logger.error("BankInteractServiceImpl银行支付签名返回处理base对象："+ToStringBuilder.reflectionToString(base));
			
		} catch (GopayException e) {
			logger.error("BankInteractServiceImpl pay error: ", e);
			result.setResultCode(e.getErrCode());
			result.setSuccess(false);
		} catch (Exception e) {
			logger.error("BankInteractServiceImpl pay error: ", e);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
			result.setSuccess(false);
		}
		return result;
	}

	@Override
	public Result bankBack(BaseMessage base) {
		logger.error("BankInteractServiceImpl银行返回处理base对象："+ToStringBuilder.reflectionToString(base));
		Result result = new Result();
		try {
			
			if (base.getBankOrderId() == null || base.getBankOrderId().equals("")) {
				
				base.setOutStlmCd(base.getBank());
				BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), base.getBank());
				
				if(bankConfig!=null){
					//设置一级私钥路径
				
					base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
					//设置一级私钥密码
					base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
					//设置二级私钥路径
					base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
					//设置二级私钥密码
					base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
					//设置公钥路径
					base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());				
				}
				
				if (StringUtils.equals(BankConstants.BANK_LOGO_UMPAY, base.getBank())&& base instanceof UmPayMessage) {
					// 验签
					MtPayInteractRemoteService bankService = (MtPayInteractRemoteService) SpringContextUtil.getBean("UMPAY-MTPAY");
					result = bankService.bankBack(base);
					base = (BaseMessage) result.get("res");
					logger.error("BankInteractServiceImpl验签返回处理base对象："+ToStringBuilder.reflectionToString(base));
					if (result.isSuccess()&& (Boolean) result.getDefaultModel()) {
						// 验签成功
						bankOrderManager.updateBackSuccess(base.getOrderId());
						logger.error("返回处理结果：订单号【"+base.getOrderId()+"】验签成功，bis_bank_main_order表更新成功状态");
					} else {
						// 验签失败
						bankOrderManager.updateBackVerifyFail(base.getOrderId());
						logger.error("返回处理结果：订单号【"+base.getOrderId()+"】验签失败，bis_bank_main_order表更新失败状态");
					}
				}
			
				logger.error("BankInteractServiceImpl验签返回处理base对象："+ToStringBuilder.reflectionToString(base));
				BankOrder bankOrder = null;
				bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
				base.setOrderId(bankOrder.getOrderId());
				// 是否验签成功过
				if (StringUtils.equals(bankOrder.getOrderStatus(),BankOrderStatus.BANK_CALL_SUCCESS)) {
					result.setDefaultModel(true);
					result.setSuccess(true);
				}
				return result;
			}
			
			BankOrder bankOrder = null;
			bankOrder = bankOrderManager.getBankOrderById(base.getBankOrderId());
        	String bankBizProdCode = bankOrder.getBankBizProdCode();
        	base.setOrderId(bankOrder.getOrderId());
        	if(BisBankBusinessProd._00.value.equals(bankBizProdCode)){
        		base.setBankBusProd(BisBankBusinessProd._00);
        	}else if(BisBankBusinessProd._01.value.equals(bankBizProdCode)){
        		base.setBankBusProd(BisBankBusinessProd._01);
        	}else if(BisBankBusinessProd._05.value.equals(bankBizProdCode)){
        		base.setBankBusProd(BisBankBusinessProd._05);
        	}else{
            	throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
            }
        	//如果为外部平台订单
			if(BisPayCheckUtils.checkExternalOrderID(bankOrder.getOrderId())){
				//获取外部订单交易对象
				BisPayMessage bisPayMessage = bisPayMessageManager.getBisPayMessageByGopayOrderId(bankOrder.getOrderId());
				//如果使用外部平台自己的订单
				if(bisPayMessage.getIsThroughBis().equals("1")){
					base.setOutStlmCd(base.getBank());
					BisBankMerchant bisBankMerchant = bisExternalPlatformService.getBankMerchant(bisPayMessage.getPlatformId(), bankOrder.getBankCode(), base.getBankBusProd().value);
	                //设置一级私钥路劲
					base.setPrivateKeyPath(bisBankMerchant.getIntrMerPravkeyPath());
	                //设置一级私钥密码
					base.setPrivatePwd(bisBankMerchant.getIntrMerPravkeyPwd());
	    			//设置二级私钥路径
					base.setPrivateKeyPath2nd(bisBankMerchant.getIntrMer2ndPravkeyPath());
	    			//设置二级私钥密码
					base.setPrivatePwd2nd(bisBankMerchant.getIntrMer2ndPravkeyPwd());             
	                //设置公钥路径
					base.setPublicKeyPath(bisBankMerchant.getIntrBankPubkeyPath());	
				}else{
					base.setOutStlmCd(base.getBank());
					BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), bankOrder.getBankCode());
					//设置一级私钥路径
					base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
					//设置一级私钥密码
					base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
					//设置二级私钥路径
					base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
					//设置二级私钥密码
					base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
					//设置公钥路径
					base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
				}
			}else{
				base.setOutStlmCd(base.getBank());
				BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankCodeAndBankBusProd(base.getBankBusProd(), bankOrder.getBankCode());
				//设置一级私钥路径
				base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
				//设置一级私钥密码
				base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
				//设置二级私钥路径
				base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
				//设置二级私钥密码
				base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
				//设置公钥路径
				base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
			}
			String beanName = "";
			//如果定单为外部平台
			if(BisPayCheckUtils.checkExternalOrderID(bankOrder.getOrderId())){
				beanName = getExternalBeanName(base,bankOrder);
			}else{
				// 获取订单信息与银行信息
				CpsGenMainOrder mainOrder = getMainOrder(bankOrder.getOrderId());
				// 获取SPRING加载的BeanName
				beanName = getBeanName(mainOrder,BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()),BisBankBusinessProd.get(bankOrder.getBankBizProdCode()));
			}

			/****************** 处理银行多次通知 begin ***********************/
			// 是否验签成功过
			if (StringUtils.equals(bankOrder.getOrderStatus(),BankOrderStatus.BANK_CALL_SUCCESS)) {
				MtPayInteractRemoteService bankService = (MtPayInteractRemoteService) SpringContextUtil.getBean(beanName);
				result = bankService.bankBack(base);
				result.setDefaultModel(true);
				result.setSuccess(true);
				return result;
			}
			// 是否验签失败过
			if (StringUtils.equals(bankOrder.getOrderStatus(),BankOrderStatus.VERIFY_FAIL)) {
				result.setDefaultModel(false);
				result.setSuccess(true);
				return result;
			}
			/************** 处理银行多次通知 end *******************/
			// 验签
			MtPayInteractRemoteService bankService = (MtPayInteractRemoteService) SpringContextUtil.getBean(beanName);
			result = bankService.bankBack(base);				
			if (base.isFront()) {
				// 前台通知不更新银行流水状态，直接返回
				return result;
			}
			if (result.isSuccess() && (Boolean) result.getDefaultModel()) {
				// 验签成功
				bankOrderManager.updateBackSuccess(bankOrder.getOrderId());
				logger.error("银行【 "+beanName+"】返回处理结果：国付宝订单号【"+base.getOrderId()+"】验签成功，bis_bank_main_order表更新成功状态");
			} else {
				// 验签失败
				bankOrderManager.updateBackVerifyFail(bankOrder.getOrderId());
				logger.error("银行【 "+beanName+"】返回处理结果：国付宝订单号【"+base.getOrderId()+"】验签失败，bis_bank_main_order表更新失败状态");
			}
		
		} catch (GopayException e) {
			logger.error("BankInteractServiceImpl bankBack error: ", e);
			result.setResultCode(e.getErrCode());
			result.setSuccess(false);
		} catch (Exception e) {
			logger.error("BankInteractServiceImpl bankBack error: ", e);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
			result.setSuccess(false);
		}
		return result;
	}


	@Override
	public Result query(BaseMessage base) {
		logger.error("BankInteractServiceImpl银行查询处理base对象："+ToStringBuilder.reflectionToString(base));
		Result result = new Result();
		try {
			CpsGenMainOrder mainOrder = getMainOrder(base.getOrderId());
			// 获取SPRING加载的BeanName
			String outStlmId = getOutStlmId(mainOrder,base.getBankIntrChann(),base.getBankBusProd());
			base.setOutStlmCd(outStlmId);
			base.setAmount(mainOrder.getTotalOrderAmt());
			if (mainOrder.getSettleAmt() != null) {
	            // 发送银行金额取结算金额,若为空则取总金额字段
	            base.setAmount(mainOrder.getSettleAmt());
	        }
			String beanName = getBeanName(mainOrder,base.getBankIntrChann(),base.getBankBusProd());
			MtPayInteractRemoteService bankService = (MtPayInteractRemoteService) SpringContextUtil.getBean(beanName);
			if(!BisPayCheckUtils.checkExternalOrderID(base.getOrderId())){
				// 根据银行业务产品代码、通道代码、银行代码获取通道配置信息
				BaseBisBankExtConfig bankConfig = bisBankExtConfigManager.findExtConfigByBankChannelAndBankBusProd(base.getBankBusProd(), base.getBankIntrChann(), base.getBank());
				//设置一级私钥路径
				base.setPrivateKeyPath(bankConfig.getIntrMerPravkeyPath());
				//设置一级私钥密码
				base.setPrivatePwd(bankConfig.getIntrMerPravkeyPwd());
				//设置二级私钥路径
				base.setPrivateKeyPath2nd(bankConfig.getIntrMer2ndPravkeyPath());
				//设置二级私钥密码
				base.setPrivatePwd2nd(bankConfig.getIntrMer2ndPravkeyPwd());
				//设置公钥路径
				base.setPublicKeyPath(bankConfig.getIntrBankPubkeyPath());
				//设置商户号
				base.setMerID(bankConfig.getIntrMernum1());
				//设置二级商户号
				base.setMerID2nd(bankConfig.getIntrMernum2());
				//设置结算账户网点联行号
				base.setBranchCode(bankConfig.getBranchCode());
				//设置银行查询地址
				base.setQueryUrl(bankConfig.getQueryUrl());	
			}
			//查询
			result = bankService.query(base);
			logger.error("BankInteractServiceImpl银行查询返回base对象："+ToStringBuilder.reflectionToString(result));
		} catch (GopayException e) {
			logger.error("BankInteractServiceImpl query error: ", e);
			result.setResultCode(e.getErrCode());
			result.setSuccess(false);
		} catch (Exception e) {
			logger.error("BankInteractServiceImpl query error: ", e);
			result.setResultCode(ProcCodeConstants.PROC_CODE_100F1002);
			result.setSuccess(false);
		}
		return result;
	}

	public Result refund(BaseMessage base) {
		return null;
	}

	public Result dayend(BaseMessage base) {
		return null;
	}

	/**
	 * 获取订单信息
	 * 
	 * @param base
	 * @return
	 * @throws GopayException
	 */
	private CpsGenMainOrder getMainOrder(String orderId) throws GopayException {
		if (orderId == null || "".equals(orderId)) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
		}
		// 获取主订单表
		CpsGenMainOrder mainOrder = mainOrderQuery.get(orderId);
		if (mainOrder == null) {
			throw new GopayException(ProcCodeConstants.PROC_CODE_100E5041);
		}
		return mainOrder;
	}

	/**
	 * 获取SPRING加载的BeanName
	 * 
	 * <pre>
	 * BeanName规范:银行编码-交易类型，如TBANK-B2B
	 * </pre>
	 * 
	 * @param mainOrder
	 *            订单信息
	 * @param bankInfo
	 *            银行信息
	 * @return
	 * @throws GopayException
	 */
	private String getBeanName(CpsGenMainOrder mainOrder,BisBankInterfaceChannel inChann, BisBankBusinessProd bankBusProd)throws GopayException {
		String beanSuffix = TradeType.getOrderTrandType(mainOrder.getPayChannel());
		String outStlmId = getOutStlmId(mainOrder,inChann,bankBusProd);
		String beanName = outStlmId + "-" + beanSuffix;
		return beanName;
	}

    /**
     * 获取SPRING加载的BeanName
     * 
     * <pre>
     * BeanName规范:银行编码-交易类型，如TBANK-B2B
     * </pre>
     * 
     * @param mainOrder
     *            订单信息
     * @param bankInfo
     *            银行信息
     * @return
     * @throws GopayException
     */
    private String getExternalBeanName(BaseMessage message,BankOrder bankOrder) throws GopayException {
        String beanName ="";
        if (bankOrder != null) {
        	String beanSuffix="";
        	String outStlmId="";
        	String chennelCodeValue = BisBankInterfaceChannel.get(bankOrder.getInterfaceChennelCode()).value;
        	String bankBizProdCode = BisBankBusinessProd.get(bankOrder.getBankBizProdCode()).value;        	
        	if(BisBankBusinessProd._05.value.equals(bankBizProdCode)){
        		beanSuffix = "MTPAY";
        	}else{
            	throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
            }
    		if (StringUtils.equals(TradeType.TRADE_TYPE_MTPAY, beanSuffix)) {
    			outStlmId = InitialSpringBeanName.getOutStlmCd(chennelCodeValue,bankBizProdCode,bankOrder.getBankCode());
    		} else {
    			outStlmId = bankOrder.getBankCode();
    		}
    		message.setBank(outStlmId);
        	beanName = outStlmId+"-"+beanSuffix;
        	return beanName;
        }else{
        	throw new GopayException(ProcCodeConstants.PROC_CODE_100E1141);
        }
    }
	
	private String getOutStlmId(CpsGenMainOrder mainOrder,BisBankInterfaceChannel inChann, BisBankBusinessProd bankBusProd)throws GopayException {
		String beanSuffix = TradeType.getOrderTrandType(mainOrder.getPayChannel());
		String outStlmId = "";
		if (StringUtils.equals(TradeType.TRADE_TYPE_MTPAY, beanSuffix)) {
			outStlmId = InitialSpringBeanName.getOutStlmCd(inChann.value,bankBusProd.value, mainOrder.getOutStlmId());
		} else {
			outStlmId = mainOrder.getOutStlmId();
		}
		return outStlmId;
	}

	@Override
	public Result flush(BaseMessage base) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Result certification(BaseMessage baseMsg) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Result sendSms(BaseMessage baseMsg) {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public Result checkSms(BaseMessage baseMsg) {
		// TODO Auto-generated method stub
		return null;
	}
}